package ink.feny.security.config;

import ink.feny.security.filter.JwtTokenFilter;
import ink.feny.security.filter.LoginFilter;
import ink.feny.security.property.JwtAuthProperty;
import ink.feny.security.service.UserAuthProvider;
import ink.feny.security.service.UserAuthService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.savedrequest.RequestCache;

/**
 * Spring Security Jwt配置
 * @author Feny
 * @date Created in 2021/4/28
 */
@Configuration
@EnableWebSecurity
public class JwtSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private JwtAuthProperty property;

    @Bean
    public JwtTokenFilter jwtTokenFilter() {
        return new JwtTokenFilter();
    }

    @Bean
    public LoginFilter loginFilter() throws Exception {
       return new LoginFilter(authenticationManagerBean());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 由于使用的是JWT，我们这里不需要csrf
        // 基于token，所以不需要session
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                // 禁用缓存
                .and().headers().cacheControl();

        // 白名单接口，至少有一个
        String[] exceptUrls = property.getExceptUrl().split(",");

        http.formLogin().loginPage("/login.html")
                .loginProcessingUrl("/auth/login")
                .and()
                .addFilter(loginFilter())
                .addFilterBefore(jwtTokenFilter(), UsernamePasswordAuthenticationFilter.class)
                .authorizeRequests()
                .antMatchers(exceptUrls).permitAll()
                .anyRequest().authenticated()
                .and().csrf().disable();
    }

    @Autowired
    private UserAuthService authService;
    @Autowired
    private UserAuthProvider userAuthProvider;

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(userAuthProvider)
                .userDetailsService(authService).passwordEncoder(passwordEncoder());
    }
}
